package xyz.bali16.module.chat.controller;


import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.tio.core.Tio;
import xyz.bali16.application.config.prop.AuthProp;
import xyz.bali16.application.core.model.Result;
import xyz.bali16.application.core.utils.AuthUtils;
import xyz.bali16.application.core.utils.TimeUtil;
import xyz.bali16.application.entity.User;
import xyz.bali16.application.service.UserService;
import xyz.bali16.module.chat.entity.ChatGroup;
import xyz.bali16.module.chat.entity.ChatGroupUser;
import xyz.bali16.module.chat.entity.ChatUserGroupMessage;
import xyz.bali16.module.chat.model.BaseRequestVO;
import xyz.bali16.module.chat.model.GroupVO;
import xyz.bali16.module.chat.service.ChatGroupService;
import xyz.bali16.module.chat.service.ChatGroupUserService;
import xyz.bali16.module.chat.service.ChatUserGroupMessageService;
import xyz.bali16.module.chat.websocket.ImConfigConst;
import xyz.bali16.module.chat.websocket.TioWebsocketStarter;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/imChatGroup")
public class ChatGroupController {

    @Autowired
    private ChatGroupService chatGroupService;

    @Autowired
    private ChatGroupUserService chatGroupUserService;

    @Autowired
    private TioWebsocketStarter tioWebsocketStarter;

    @Autowired
    private ChatUserGroupMessageService chatUserGroupMessageService;
    @Autowired
    @AutowiredType(AutowiredType.Type.PLUGIN_MAIN)
    private UserService userService;
    @Autowired
    @AutowiredType(AutowiredType.Type.PLUGIN_MAIN)
    private AuthProp authProp;
    /**
     * 创建群组
     */
    @PostMapping("/addGroup")
    //@PreAuthorize("@auth.permission('plugin:chat:group:add')")
    public Result addGroup(@RequestBody ChatGroup chatGroup) {
        // 设置组类型为组类型
        chatGroup.setGroupType(ImConfigConst.GROUP_COMMON);

        String username = AuthUtils.getCurrentUsername();
        User user = userService.getByUsername(username);
        String userId = user.getUserId();

        // 设置群主id
        chatGroup.setGroupAdminId(userId);
        chatGroupService.save(chatGroup);

        // 设置群聊用户
        ChatGroupUser chatGroupUser = new ChatGroupUser();
        chatGroupUser.setGroupId(chatGroup.getId());
        chatGroupUser.setUserId(userId);
        chatGroupUser.setAdminFlag(ImConfigConst.ADMIN_FLAG_TRUE);
        chatGroupUser.setStatus(ImConfigConst.GROUP_USER_STATUS_PASS);
        chatGroupUserService.save(chatGroupUser);

        Tio.bindGroup(tioWebsocketStarter.getServerTioConfig(),userId, String.valueOf(chatGroup.getId()));

        return Result.success();
    }

    /**
     * 创建话题
     */
    @PostMapping("/addGroupTopic")
    //@PreAuthorize("@auth.permission('plugin:chat:groupTopic:add')")
    public Result addGroupTopic(@RequestBody ChatGroup chatGroup) {
        // 设置组类型为话题类型
        chatGroup.setGroupType(ImConfigConst.GROUP_TOPIC);

        String username = AuthUtils.getCurrentUsername();
        User user = userService.getByUsername(username);
        String userId = user.getUserId();
        // 设置话题管理员
        chatGroup.setGroupAdminId(userId);
        // 设置进入方式
        chatGroup.setJoinType(ImConfigConst.JOIN_TYPE_FALSE);
        chatGroupService.save(chatGroup);
        return Result.success();
    }


    /**
     * 更新组
     * <p>
     * 只有群主才能修改组
     */
    @PostMapping("/updateGroup")
    //@PreAuthorize("@auth.permission('plugin:chat:group:update')")
    public Result updateGroup(@RequestBody ChatGroup chatGroup) {
        String username = AuthUtils.getCurrentUsername();
        User user = userService.getByUsername(username);
        String userId = user.getUserId();

        LambdaUpdateChainWrapper<ChatGroup> lambdaUpdate = chatGroupService.lambdaUpdate();
        lambdaUpdate.eq(ChatGroup::getId, chatGroup.getId());
        lambdaUpdate.eq(ChatGroup::getGroupAdminId, userId);
        // 群名
        if (StringUtils.hasText(chatGroup.getGroupName())) {
            lambdaUpdate.set(ChatGroup::getGroupName, chatGroup.getGroupName());
        }
        // 头像
        if (StringUtils.hasText(chatGroup.getAvatar())) {
            lambdaUpdate.set(ChatGroup::getAvatar, chatGroup.getAvatar());
        }
        // 简介
        if (StringUtils.hasText(chatGroup.getIntroduction())) {
            lambdaUpdate.set(ChatGroup::getIntroduction, chatGroup.getIntroduction());
        }
        // 群通知
        if (StringUtils.hasText(chatGroup.getNotice())) {
            lambdaUpdate.set(ChatGroup::getNotice, chatGroup.getNotice());
        }
        // 修改进入方式
        if (chatGroup.getJoinType() != null) {
            lambdaUpdate.set(ChatGroup::getJoinType, chatGroup.getJoinType());
        }
        // 转让群
        if (chatGroup.getGroupAdminId() != null) {
            lambdaUpdate.set(ChatGroup::getGroupAdminId, chatGroup.getGroupAdminId());
        }
        boolean isSuccess = lambdaUpdate.update();
        if (isSuccess && StringUtils.hasText(chatGroup.getNotice())) {
            // todo 发送群公告
        }
        return Result.success();
    }

    /**
     * 解散群
     */
    @GetMapping("/deleteGroup")
    //@PreAuthorize("@auth.permission('plugin:chat:group:delete')")
    public Result deleteGroup(@RequestParam("id") Integer id) {
        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String userId = currentUser.getUserId();

        boolean isSuccess;
        // 如果是全局管理员
        if (AuthUtils.getCurrentRoleId().equals(authProp.getSuperRoleCode())) {
            isSuccess = chatGroupService.removeById(id);
        } else { // 是否为群组管理员
            LambdaUpdateChainWrapper<ChatGroup> lambdaUpdate = chatGroupService.lambdaUpdate();
            lambdaUpdate.eq(ChatGroup::getId, id);
            lambdaUpdate.eq(ChatGroup::getGroupAdminId, userId);
            isSuccess = lambdaUpdate.remove();
        } // 如果删除成功
        if (isSuccess) {
            // 删除群组里的用户
            LambdaUpdateChainWrapper<ChatGroupUser> lambdaUpdate = chatGroupUserService.lambdaUpdate();
            lambdaUpdate.eq(ChatGroupUser::getGroupId, id).remove();
            // 删除群组聊天记录
            LambdaUpdateChainWrapper<ChatUserGroupMessage> messageLambdaUpdateChainWrapper = chatUserGroupMessageService.lambdaUpdate();
            messageLambdaUpdateChainWrapper.eq(ChatUserGroupMessage::getGroupId, id).remove();
            Tio.removeGroup(tioWebsocketStarter.getServerTioConfig(), String.valueOf(id), "remove group");
        }
        return Result.success();
    }

    /**
     * 管理员查询所有群
     */
    @PostMapping("/listGroupForAdmin")
    //@PreAuthorize("@auth.permission('plugin:chat:group:query')")
    public Result<BaseRequestVO> listGroupForAdmin(@RequestBody BaseRequestVO baseRequestVO) {
        LambdaQueryChainWrapper<ChatGroup> lambdaQuery = chatGroupService.lambdaQuery();
        lambdaQuery.orderByDesc(ChatGroup::getGmtCreated).page(baseRequestVO);
        return Result.success(baseRequestVO);
    }

    /**
     * 加入话题
     */
    @GetMapping("/addGroupTopic")
    //@PreAuthorize("@auth.permission('plugin:chat:groupToipc:add')")
    public Result addGroupTopic(@RequestParam("id") Integer id) {
        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String userId = currentUser.getUserId();

        LambdaQueryChainWrapper<ChatGroup> lambdaQuery = chatGroupService.lambdaQuery();
        Integer count = lambdaQuery
                .eq(ChatGroup::getId, id)
                .eq(ChatGroup::getGroupType, ImConfigConst.GROUP_TOPIC).count();
        // 如果查到该id是话题
        if (count == 1) {
            Tio.bindGroup(tioWebsocketStarter.getServerTioConfig(), userId, String.valueOf(id));
        }

        return Result.success();
    }

    /**
     * 用户查询所有群
     * <p>
     * 只查询审核通过和禁言的群
     */
    @GetMapping("/listGroup")
    //@PreAuthorize("@auth.permission('plugin:chat:group:query')")
    public Result<List<GroupVO>> listGroup() {
        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String userId = currentUser.getUserId();
        // 查询用户的群组
        LambdaQueryChainWrapper<ChatGroupUser> lambdaQuery = chatGroupUserService.lambdaQuery();
        lambdaQuery.eq(ChatGroupUser::getUserId, userId);
        // 包括了审批通过、禁言状态
        lambdaQuery.in(ChatGroupUser::getStatus, ImConfigConst.GROUP_USER_STATUS_PASS, ImConfigConst.GROUP_USER_STATUS_SILENCE);
        List<ChatGroupUser> groupUsers = lambdaQuery.list();

        Map<Integer, ChatGroupUser> groupUserMap = groupUsers.stream().collect(Collectors.toMap(ChatGroupUser::getGroupId, Function.identity()));
        LambdaQueryChainWrapper<ChatGroup> wrapper = chatGroupService.lambdaQuery();
        // 查找话题
        wrapper.eq(ChatGroup::getGroupType, ImConfigConst.GROUP_TOPIC);
        if (!CollectionUtils.isEmpty(groupUserMap.keySet())) {
            wrapper.or(w -> w.in(ChatGroup::getId, groupUserMap.keySet())
                    .eq(ChatGroup::getGroupType, ImConfigConst.GROUP_COMMON));
        }
        List<ChatGroup> chatGroups = wrapper.list();
        List<GroupVO> groupVOS = chatGroups.stream().map(imChatGroup -> {
            ChatGroupUser chatGroupUser = groupUserMap.get(imChatGroup.getId());
            if (chatGroupUser == null) {
                chatGroupUser = new ChatGroupUser();
                chatGroupUser.setStatus(ImConfigConst.GROUP_USER_STATUS_PASS);
                chatGroupUser.setGmtCreated(TimeUtil.getNowTimeToSeconds());
                chatGroupUser.setUserId(userId);

                chatGroupUser.setAdminFlag(userId.equals(authProp.getSuperRoleCode()));
            }
            return getGroupVO(imChatGroup, chatGroupUser);
        }).collect(Collectors.toList());
        return Result.success(groupVOS);
    }

    // 避免敏感信息泄露
    private GroupVO getGroupVO(ChatGroup chatGroup, ChatGroupUser chatGroupUser) {
        GroupVO groupVO = new GroupVO();
        groupVO.setGroupName(chatGroup.getGroupName());
        groupVO.setAvatar(chatGroup.getAvatar());
        groupVO.setIntroduction(chatGroup.getIntroduction());
        groupVO.setNotice(chatGroup.getNotice());
        groupVO.setJoinType(chatGroup.getJoinType());
        groupVO.setGroupType(chatGroup.getGroupType());
        groupVO.setId(chatGroup.getId());
        groupVO.setGmtCreated(chatGroupUser.getGmtCreated());
        groupVO.setUserStatus(chatGroupUser.getStatus());
        groupVO.setAdminFlag(chatGroupUser.getAdminFlag());
        groupVO.setMasterFlag(chatGroup.getGroupAdminId().equals(chatGroupUser.getUserId()));
        return groupVO;
    }
}

